package com.untour.seqid.config.leaf.segment.model;

import lombok.Data;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;


@Getter
@Setter
public class SegmentBuffer implements Serializable {
    //业务标识
    private String bizTag;

    //是否初始化完成
    private volatile boolean initOk;

    //号段
    private SegmentInfo segmentInfo;

    //初始化下一段缓存锁
    private Semaphore initNextSegmentLock = new Semaphore(1, true);

    //号段读写锁
    private ReadWriteLock segmentLock = new ReentrantReadWriteLock(true);

    //更新号段标识
    private volatile long updateCacheTimestamp = 0;

    @Data
    public static class SegmentInfo implements Serializable {
        //号段最大值
        private long maxId;
        //号段步长
        private int step;
        //号段当前值
        private AtomicLong value = new AtomicLong(0);
        //下一个号段缓存
        private SegmentInfo next;

        /**
         * 是否需要初始化二级缓存
         *
         * @return
         */
        public boolean needInitNext(long incrValue) {
            return this.next == null && (this.maxId - this.value.get() < 0.1 * this.step || this.maxId - this.value.get() + incrValue < 0.1 * this.step);
        }

        /**
         * 设置号段的起始值
         */
        public void initValue() {
            this.value.set(this.maxId - this.step);
        }

        /**
         * 判断是否可以切换缓存
         *
         * @return
         */
        public boolean needSwitchNext(long incrValue) {
            return this.next != null && (this.maxId <= this.value.get() || this.maxId <= this.value.get() + incrValue);
        }
    }

}
